package com.witsight.hibernate.config;

import java.net.URL;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.jta.JtaTransactionManager;

import com.witsight.platform.util.lang.ObjectUtil;
import com.witsight.platform.util.lang.StringUtil;

/**   
 * 说明：Jpa 自动配置配置
 * @Title: JpaAutoConfiguration.java 
 * @Package com.witsight.hibernate.config 
 * @See: {@link HibernateJpaAutoConfiguration}
 * Copyright: Copyright (c) 2017
 * Company:sany huax witsight team by product
 * @author: fuyp  
 * @date: 2017年9月14日 上午10:40:44 
 * @version: V1.0
 *
 */
@Configuration
@EnableConfigurationProperties(JpaHibernateProperties.class)
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class })
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
public class JpaAutoConfiguration extends HibernateJpaAutoConfiguration {
	/**
	 * 说明：定义后能再同一类中使用static常量log
	 */
	private static final Logger log = LoggerFactory.getLogger(JpaAutoConfiguration.class);
	@Autowired
	private JpaHibernateProperties jpaHibernateProperties;
	/**
	 * 
	 * 说明：构造函数 
	 * @Title:JpaAutoConfiguration.java
	 * @See: 构造函数 
	 * @param dataSource 数据源（alibaba的数据源对象）
	 * @param jpaProperties jpa属性配置对象
	 * @param jtaTransactionManager 事物
	 * @param transactionManagerCustomizers 自定义的事物管理
	 * @date 2017年9月14日 上午11:27:54
	 */
	public JpaAutoConfiguration(DataSource dataSource, JpaProperties jpaProperties,
	        ObjectProvider<JtaTransactionManager> jtaTransactionManager,
	        ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
		super(dataSource, jpaProperties, jtaTransactionManager, transactionManagerCustomizers);
	}
	
	protected EntityManagerFactoryBuilder.EntityManagerFactoryBeanCallback getVendorCallback() {
		// 加载XML配置Sql和Hql的集合
		return new EntityManagerFactoryBuilder.EntityManagerFactoryBeanCallback() {
			// 以"META-INF"为开头的地址
			private static final String START_PATH = "META-INF";
			/**
			 * 
			 * 说明：加载hql／sql的配置文件
			 * @Title: getMappingResources
			 * @See: #jpaHibernateProperties.getSqlConfigs()
			 * @author fuyp
			 * @return 配置文件地址集合
			 * @date: 2017年9月14日 下午2:22:05
			 */
			private String[] getMappingResources() {
				Resource[] resources = jpaHibernateProperties.getSqlConfigs(); 
				if (ObjectUtil.isEmpty(resources)) {
					return new String[] {};
				}
				String[] mappingResources = new String[] {};
				for (Resource resource : resources) {
					try {
						URL url = resource.getURL();
						String path = url.toExternalForm();
						int startIndex = StringUtil.lastIndexOf(path, START_PATH);
						mappingResources = ObjectUtil.addObjectToArray(mappingResources, StringUtil.substring(path, startIndex));
					} catch (Exception e) {
						log.error("xml config sql/hql error.", e);
					}
				}
				return mappingResources;
			}
			@Override
			public void execute(LocalContainerEntityManagerFactoryBean factory) {
				// 加载hql／sql的配置文件
				factory.setMappingResources(this.getMappingResources());
			}
		};
	}
}
